<?php

namespace LhpAmis\Plugin\TableBuilder;

use LhpAmis\Plugin\FormBuilder\FormBuilder;
use LhpAmis\Renderers\BaseApi;
use LhpAmis\Renderers\BaseRenderer;
use LhpAmis\Renderers\CRUDTable;
use LhpAmis\Renderers\Operation;
use LhpAmis\Renderers\TableColumn;
use LhpAmis\Traits\BaseApiTrait;
use LhpAmis\Traits\ButtonsTrait;
use LhpAmis\Renderers\Amis;

class TableBuilder extends CRUDTable
{
    use BaseApiTrait;
    use ButtonsTrait;


    /**
     * 列表列配置
     * @var array
     */
    protected array $columns = [];

    /**
     * 筛选条件表单配置
     * @var object
     */
    protected object $filter;

    /**
     * 列表数据主键
     * @var string
     */
    protected string $primaryKey = 'id';

    /**
     * API接口对象
     * @var  
     */
    protected $api;

    /**
     * 快速保存 API接口对象
     * @var BaseApi
     */
    protected $quickSaveApi;
    /**
     * 快速单行数据保存 API接口对象
     * @var BaseApi
     */
    protected $quickSaveItemApi;
    /**
     * 行操作按钮
     * @var array
     */
    protected array $rowActions = [];

    /**
     * 列表头部工具栏操作按钮
     * @var array
     */
    protected array $headerToolbarActions = [];

    /**
     * 批量操作
     */
    protected array $bulkActions = [];


    /**
     * 指定列属性设置数组
     */
    protected array $columnAttrs = [];


    public function __construct()
    {
        parent::__construct();


        $this->syncLocation(false);
        $this->affixHeader(false);
        $this->filterDefaultVisible(false);
        $this->autoFillHeight(false);
        $this->alwaysShowPagination(true);

        $this->filter = FormBuilder::make();
        $this->filter->isFilter(true);
        $this->bulkActions($this->bulkActions);

        $this->setApi($this->BaseApiPost());
        $this->setQuickSaveApi($this->BaseApiPut('modify'));
    }
    /**
     * 构建CRUD列表Amis配置
     * @return array
     */
    public function filteredResults(): array
    {

        $this->headerToolbarActions();
        $this->filter->api($this->api);
        $filter = json_decode(json_encode($this->filter), true);
        $this->filter->unset('type');
        if (isset($filter['body']) && !empty($filter['body'])) {
            $this->headerToolbarActions[] = Amis::make('filter-toggler')->align('right');

            $this->filter->set('panelClassName', 'base-filter');

            $this->filter = $this->filter->actions([
                Amis::make()->Button()->label('重置')->actionType('clear-and-submit'),
                Amis::make('submit')->label('搜索')->level('primary'),
            ]);

            $this->filter($this->filter);
        }

        $this->api($this->api);

        $this->perPageField($this->perPageField);
        $this->perPage($this->perPage);
        $this->filterTogglable();
        $this->quickSaveApi($this->quickSaveApi);
        // $this->quickSaveItemApi($this->quickSaveItemApi);
        $this->bulkActions($this->bulkActions);
        $this->perPageAvailable($this->perPageAvailable);
        $this->footerToolbar($this->baseFooterToolBar);
        $this->headerToolbar($this->headerToolbarActions);
        $this->columns($this->buildColumn());


        return $this->toArray();
    }
    /**
     * 构建静态对象
     * @return TableBuilder
     */
    public static function make()
    {
        return new self();
    }

    /**
     * @param    $api
     * @return $this
     */
    public function setApi($api): TableBuilder
    {
        $this->api = $api;
        return $this;
    }

    /**
     * @param   $quickSaveApi
     * @return $this
     */
    public function setQuickSaveApi($api): TableBuilder
    {
        $this->quickSaveApi = $api;
        return $this;
    }


    /**
     * @param   $quickSaveItemApi
     * @return $this
     */
    public function setQuickSaveItemApi($api): TableBuilder
    {
        $this->quickSaveItemApi = $api;
        return $this;
    }

    function setFilter($key, $value)
    {
        $this->filter->set($key, $value);
        return $this;
    }

    /**
     * 设置搜索条件字段
     * @param string $name
     * @param string $label
     * @param string $type
     * @param mixed $description
     * @param mixed $value
     * @param array $options
     * @param array $
     * @return static
     */
    function setSearchItem($name, string $label = '', string $type = 'text', string $description = '', $value = '')
    {
        $this->filter->addFormItem($name, $label, $type, $description, $value);
        return $this;
    }
    /**
     * 批量设置搜索条件字段
     * @param mixed $filterItems
     * @return static
     */
    function setSearchItems($filterItems = [])
    {
        $this->filter->addFormItems($filterItems);
        return $this;
    }


    protected $ImageUrlDomain = [];

    /**
     * 设置图片域名
     * @param mixed $filed
     * @param mixed $domain
     * @return static
     */
    public function setImageUrlDomain($filed, $domain)
    {
        $this->ImageUrlDomain[$filed] = $domain;
        return $this;
    }

    /**
     * 批量设置图片域名
     * $fileds=>[
     *  'filed1'=>'http://www.domain1.com',
     *  'filed2'=>'http://www.domain2.com',
     * ]
     * @param mixed $fileds
     * @return static
     */
    public function setImageUrlDomainFields($fileds = [])
    {
        foreach ($fileds as $filed => $domain) {
            $this->setImageUrlDomain($filed, $domain);
        }
        return $this;
    }

    /**
     * 设置列属性
     * @param string $field
     * @param string $attr
     * @param string $value
     * @return void
     */
    public function setColumnAttr(string $field, string $attr, string $value)
    {
        $this->columnAttrs[$field][] = [$attr => $value];
        return $this;
    }

    /**
     * 批量设置列属性
     * 支持字符串逗号分隔多个字段
     * @param array|string $Attrs 数组属性或者字符串字段名称
     * @param array $values 当 $Attrs 为字符串则当前参数为列属性数组
     * @return void
     */
    public function setColumnAttrs($Attrs = [], $values = [])
    {
        if (is_array($Attrs) && empty($values)) {
            foreach ($Attrs as $field => $attrs) {
                $this->columnAttrs[$field] = $attrs;
            }
        } else if (is_string($Attrs) && !empty($values)) {
            $fileds = explode(',', $Attrs);
            foreach ($fileds as $field) {
                $this->columnAttrs[$field] = $values;
            }
        } else if (is_array($Attrs) && !empty($values)) {
            $fileds = $Attrs;
            foreach ($fileds as $field) {
                $this->columnAttrs[$field] = $values;
            }
        }

        return $this;
    }
    private function appendColumnAttr(&$column)
    {
        $columnFiled = $column->get('name');
        if (isset($this->columnAttrs[$columnFiled])) {
            $Attrs = $this->columnAttrs[$columnFiled];
            $column->batchSet($Attrs);
        }
    }
    /**
     * 添加列配置
     * @param string|object $name
     * @param string $label
     * @param string $type
     * @param string $remark
     * @param mixed ...$options 额外选项，最后一个数组参数会被拆解，其他数组参数会被合并
     * @return $this
     */
    public function addColumn($name, string $label = '', string $type = 'text', ...$options): TableBuilder
    {
        $column = null;
        if (is_object($name) && $name instanceof BaseRenderer) {
            $column = $name;
        } else {
            if (empty($options)) {
                $column = ['name' => $name, 'label' => $label, 'type' => $type];
            } else {
                $column = array_merge(['name' => $name, 'label' => $label, 'type' => $type], $options);
            }
        }
        if ($column !== null) {
            $this->columns[] = $column;
        }

        return $this;
    }


    /**
     * 批量添加列配置
     * @param array $columns
     * @return $this
     */
    public function addColumns(array $columns = []): TableBuilder
    {
        foreach ($columns as $options) {
            call_user_func_array([$this, 'addColumn'], $options);
        }
        return $this;
    }
    private function buildColumn()
    {
        foreach ($this->columns as $key => $column) {
            if (is_object($column)) {
                $this->appendColumnAttr($column);
                $this->columns[$key] = $column;
                continue;
            }

            if ($column['type'] == 'btn') {
                $this->columns[$key] = $this->rowActions();
            } else {
                $column = $this->tableBuildColumn($column);
                $this->appendColumnAttr($column);
                $this->columns[$key] = $column;
            }
        }

        return $this->columns;
    }


    /**
     * 操作列
     * @return Operation
     */
    protected function rowActions(): Operation
    {
        return Amis::make()->Operation()->label('操作')->buttons($this->rowActions);
    }
    public function tableBuildColumn($column)
    {
        if (is_object($column) && $column instanceof BaseRenderer) {
            return $column;
        } elseif (is_object($column['name']) && $column['name'] instanceof BaseRenderer) {
            $Component = $column['name'];
            $name = $Component->get('name');
        } else {
            $name = $column['name'];
            $map = $this->getBuilderMaps();
            $isEditer = (strpos($column['type'], '.edit') !== false) ? true : false;
            if ($isEditer) {
                $column['type'] = str_replace('.edit', '', $column['type']);
            }

            if (isset($map[$column['type']])) {
                $ComponentClass = $map[$column['type']];
            } else {
                throw new \Exception('未找到组件' . $column['type']);
            }
            if ($column['type'] == 'text') {
                $ComponentClass = '\\LhpAmis\\Renderers\\TableColumn';
            }

            if (class_exists($ComponentClass)) {
                $Component = $ComponentClass::make();
            } else {
                throw new \Exception('未找到组件' . $ComponentClass);
            }
        }

        //设置表格字段是否可以编辑
        $Component->setTableIsEditer($isEditer);

        //判断并设置字段名称
        if ($name !== '') {
            $Component->name($name);
        }

        //判断并设置字段标签
        if ($column['label'] !== '') {
            $Component->label($column['label']);
        }

        //判断默认值是否为空并且当前组件有value方法设置默认值
        if (isset($column['value']) && method_exists($Component, 'value')) {
            $Component->value($column['value']);
        }
        if ($column['type'] == 'text') {
            $Component->tableBuildColumn($column);
        } else {
            $Component->tableBuildField($column);
        }
        return $Component;
    }
    /**
     * 设置列表工具栏导出Excel按钮
     * @param mixed $label
     * @param mixed $api
     * @return static
     */
    public function exportExcel($label = '导出Excel', $api = null)
    {
        $ExportExcel = Amis::make('export-excel')->align('right')->label($label);
        if ($api !== null) {
            $ExportExcel->api($api);
        }
        $this->headerToolbarActions[] = $ExportExcel;
        return $this;
    }

    /**
     * 设置列表工具栏导出CSV按钮
     * @param mixed $label
     * @param mixed $api
     * @return static
     */
    public function exportCsv($label = '导出CSV', $api = null)
    {
        $ExportCsv = Amis::make('export-csv')->align('right')->label($label);
        if ($api !== null) {
            $ExportCsv->api($api);
        }

        $this->headerToolbarActions[] = $ExportCsv;
        return $this;
    }
    /**
     * 基础顶部工具栏
     */
    private function headerToolbarActions(): void
    {
        $this->headerToolbarActions[] = 'bulkActions';
        $this->headerToolbarActions[] = Amis::make('reload')->align('right');
    }


    protected array $baseFooterToolBar = ['switch-per-page', 'statistics', 'pagination'];

    private function setFooter($Actions)
    {
        $this->baseFooterToolBar[] = $Actions;
    }

    protected array $perPageAvailable = [15, 20, 25, 50, 100];
    protected int $perPage = 15;
    protected string $perPageField = 'list_rows';

    public function setPerPage(int $perPage = 15)
    {
        $this->perPage = $perPage;
        return $this;
    }

    /**
     * 批量添加右侧按钮
     * @param string|array $buttons
     * @return $this
     */
    public function addRightButtons($buttons = []): TableBuilder
    {
        if (!empty($buttons)) {
            $buttons = is_array($buttons) ? $buttons : explode(',', $buttons);
            foreach ($buttons as $key => $value) {
                if (is_object($value)) {
                    $this->rowActions[] = $value->level('link');
                } elseif (is_numeric($key)) {
                    $this->addRightButton($value);
                } else {
                    $this->addRightButton($key, ...$value);
                }
            }
        }
        return $this;
    }
    /**
     * 添加列表右侧按钮
     * @param mixed $type
     * @param array $args
     * @return TableBuilder
     */
    public function addRightButton($type = '', ...$args): TableBuilder
    {
        if (is_array($type)) {
            $args = $type;
            $type = $type['type'];
        }

        switch ($type) {
            // 编辑按钮
            case 'edit':
                $this->rowActions[] = $this->rowEditerButton(...$args)->level('link');
                break;

            // 编辑按钮
            case 'status':
                $this->rowActions[] = $this->rowStatusButton(...$args)->level('link');
                break;

            // 启用按钮
            case 'enable':
                $this->rowActions[] = $this->rowEnableButton(...$args)->level('link');
                break;

            // 禁用按钮
            case 'disable':
                $this->rowActions[] = $this->rowDisableButton(...$args)->level('link');
                break;

            // 删除按钮(不可恢复)
            case 'delete':
                $this->rowActions[] = $this->rowDeleteButton(...$args)->level('link');
                break;

            // 自定义按钮
            case 'custom':
                $this->rowActions[] = $this->rowCustomButton(...$args)->level('link');
                break;
        }
        return $this;
    }
    /**
     * 添加多行操作按钮
     * @param mixed $Actions
     * @return TableBuilder
     */
    public function addTopBulkButton($Actions): TableBuilder
    {
        $this->bulkActions[] = $Actions;
        return $this;
    }
    /**
     * 批量添加多行操作按钮
     * @param mixed $buttons
     * @return TableBuilder
     */
    public function addTopBulkButtons($buttons = []): TableBuilder
    {
        if (!empty($buttons)) {
            foreach ($buttons as $value) {
                $this->addTopBulkButton($value);
            }
        }
        return $this;
    }
    /**
     * 批量添加右侧按钮
     * @param string|array $buttons
     * @return $this
     */
    public function addTopButtons($buttons = []): TableBuilder
    {
        if (!empty($buttons)) {
            $buttons = is_array($buttons) ? $buttons : explode(',', $buttons);

            foreach ($buttons as $key => $value) {
                if (is_object($value)) {
                    $this->headerToolbarActions[] = $value->level('primary');
                } elseif (is_numeric($key)) {
                    $this->addTopButton($value);
                } else {
                    $this->addTopButton($key, ...$value);
                }
            }
        }
        return $this;
    }
    /**
     * 添加头部按钮
     * @param mixed $type
     * @param array $args
     * @return TableBuilder
     */
    public function addTopButton($type = '', ...$args): TableBuilder
    {
        if (is_array($type)) {
            $args = $type;
            $type = $type['type'];
        }

        switch ($type) {
            // 创建按钮
            case 'create':
                $this->headerToolbarActions[] = $this->createButton(...$args);
                break;

            // 状态按钮
            case 'status':
                $this->bulkActions[] = $this->statusButton(...$args)->level('primary');
                break;

            // 启用按钮
            case 'enable':
                $this->bulkActions[] = $this->bulkEnableButton(...$args)->level('primary');
                break;

            // 禁用按钮
            case 'disable':
                $this->bulkActions[] = $this->bulkDisableButton(...$args)->level('primary');
                break;

            // 删除按钮(不可恢复)
            case 'delete':
                $this->bulkActions[] = $this->bulkDeleteButton(...$args)->level('danger');
                break;

            // 导出CSV
            case 'csv':
                $this->headerToolbarActions[] = $this->exportCsv(...$args)->level('danger');
                break;

            // 导出Excel
            case 'excel':
                $this->headerToolbarActions[] = $this->exportExcel(...$args)->level('danger');
                break;

            // 自定义按钮
            case 'custom':
            default:
                $this->bulkActions[] = $this->customButton(...$args)->level('danger');
                break;
        }
        return $this;
    }
    /**
     * 排序字段
     * @var array
     */
    protected $orderFields = [];
    /**
     * 添加排序字段
     * @param mixed $fileds
     * @return static
     */
    public function addOrder($fileds)
    {
        if (is_string($fileds)) {
            $fileds = explode(',', $fileds);
        }
        if (!empty($fileds)) {
            $this->orderFields = $fileds;
        }
        return $this;
    }
    /**
     * 动态设置Amis的其他属性
     * amis的属性名称为  title  
     * 使用的方式为  $this->setTitle('标题')
     * @param mixed $name
     * @param mixed $arguments
     * @return static
     */
    public function __call($name, $arguments)
    {
        if (strpos($name, 'set') !== false) {
            $name = str_replace('set', '', $name);
            $name = lcfirst($name);
            $this->set($name, ...$arguments);
        }

        return $this;
    }
}